package com.bestv.bsr.core.utils;


import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;


public class AESEncrypt {

    private static final Log logger = LogFactory.getLog(AESEncrypt.class);

    private static final String AES_ECB_ENCRYPT_MODE = "AES/ECB/PKCS5Padding";
    private static final String AES_CBC_ENCRYPT_MODE = "AES/CBC/PKCS5Padding";

    /**
     * 使用参数中的密钥加密
     *
     * @param sSrc 明文
     * @param sKey 密钥
     * @return 密文
     */
    public static String aesEcbEncryptAndBase64(String sSrc, String sKey) throws Exception {

        if (sKey == null) {
            throw new Exception("Key为空null");
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            throw new Exception("Key长度不是16位");
        }
        try {
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance(AES_ECB_ENCRYPT_MODE);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(sSrc.getBytes(StandardCharsets.UTF_8));
            // 此处使用BASE64做转码功能，同时能起到2次加密的作用。
            return new Base64().encodeToString(encrypted);
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }


    public static String aesEcbEncryptAndBase64(byte[] sSrc, String sKey) throws Exception {

        if (sKey == null) {
            throw new Exception("Key为空null");
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            throw new Exception("Key长度不是16位");
        }
        try {
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            // "算法/模式/补码方式"
            Cipher cipher = Cipher.getInstance(AES_ECB_ENCRYPT_MODE);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);
            byte[] encrypted = cipher.doFinal(sSrc);
            // 此处使用BASE64做转码功能，同时能起到2次加密的作用。
            return new Base64().encodeToString(encrypted);
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    /**
     * 使用参数中的密钥解密
     *
     * @param sSrc 密文
     * @param sKey 密钥
     * @return 明文
     */
    public static String aesEcbDecryptAndBase64(String sSrc, String sKey) throws Exception {

        // 判断Key是否正确
        if (sKey == null) {
            throw new Exception("Key为空null");
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            throw new Exception("Key长度不是16位");
        }
        try {
            byte[] raw = sKey.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance(AES_ECB_ENCRYPT_MODE);
            cipher.init(Cipher.DECRYPT_MODE, keySpec);
            // 先用base64解密
            byte[] encrypted1 = new Base64().decode(sSrc);
            byte[] original = cipher.doFinal(encrypted1);
            return new String(original, StandardCharsets.UTF_8);
        } catch (Exception ex) {
            logger.error(ex.getMessage());
            return null;
        }
    }


    /**
     * CBC aes 加密
     */
    public static String aesCbcEncrypt(String src, String key, String ivStr) {
        byte[] encrypted;
        try {
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance(AES_CBC_ENCRYPT_MODE);
            IvParameterSpec iv = new IvParameterSpec(ivStr.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
            encrypted = cipher.doFinal(src.getBytes());
            return URLEncoder.encode(new Base64().encodeToString(encrypted), "UTF-8");
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    /**
     * AES CBC  解密
     */
    public static String aesCbcDecrypt(String src, String key, String ivStr) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            Cipher cipher = Cipher.getInstance(AES_CBC_ENCRYPT_MODE);
            IvParameterSpec iv = new IvParameterSpec(ivStr.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
            byte[] decrypted = Base64.decodeBase64(URLDecoder.decode(src, "UTF-8"));
            return new String(cipher.doFinal(decrypted));
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }
}
